#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#define IDN "IDN"
#define INT10 "INT10"
#define INT8 "INT8"
#define INT16 "INT16"
#define OP "OP"
#define KEY "KEY"
#define REAL10 "REAL10"
#define REAL8 "REAL8"
#define REAL16 "REAL16"

using namespace std;



bool is16(char a) {
    if (isalnum(a)) {
        return true;
    }
    else if (a >= 'a' && a <= 'f') {
        return true;
    }
    return false;
}

bool is8(char a) {
    if (a >= '0' && a < '8') {
        return true;
    }
    return false;
}

bool isOperator(char a) {
    switch (a) {
        case '>':
        case '<':
        case '=':
        case '+':
        case '-':
        case '*':
        case '/':
        case '(':
        case ')':
        case ';':
            return true;
        default:return false;
    }
}

bool isKeyWord(string a) {//if   then   else   while  do
    if (a == "if") {
        return true;
    }
    if (a == "then") {
        return true;
    }
    if (a == "else") {
        return true;
    }
    if (a == "while") {
        return true;
    }
    if (a == "do") {
        return true;
    }
    return false;
}

double Hex2Dec(string s){
    int count = s.length();
    double sum = 0;
    int j = count;
    for (int i = 0; i < count; i++) {
        if (s[i] == '.') {
            j = i;
            break;
        }
    }
    for (int i = j - 1; i >= 2; i--){
        if (s[i] >= '0' && s[i] <= '9'){
            sum += (s[i] - 48) * pow(16, j - i - 1);
        }
        else if (s[i] >= 'A' && s[i] <= 'F'){
            sum += (s[i] - 55) * pow(16, j - i - 1);
        }
        else if (s[i] >= 'a' && s[i] <= 'f'){
            sum += (s[i] - 87) * pow(16, j - i - 1);
        }
    }
    for (int i = j + 1; i < count; i++){
        if (s[i] >= '0' && s[i] <= '9'){
            sum += (s[i] - 48) * pow(16, j - i);
        }
        else if (s[i] >= 'A' && s[i] <= 'F'){
            sum += (s[i] - 55) * pow(16, j - i);
        }
        else if (s[i] >= 'a' && s[i] <= 'f'){
            sum += (s[i] - 87) * pow(16, j - i);
        }
    }
    return sum;
}

double Oct2Dec(string s) {

    int count = s.length();
    double sum = 0;
    int j = count;
    for (int i = 0; i < count; i++) {
        if (s[i] == '.') {
            j = i;
            break;
        }
    }
    for (int i = j - 1; i >= 2; i--){
        if (s[i] >= '0' && s[i] <= '8'){
            sum += (s[i] - 48) * pow(8, j - i - 1);
        }
    }
    for (int i = j + 1; i < count; i++){
        if (s[i] >= '0' && s[i] <= '8'){
            sum += (s[i] - 48) * pow(8, j - i);
        }
    }
    return sum;
}

int scan(ifstream& in_file,ofstream& out_file){
    string str;
    char ch;
    int num = 0;
    string kind;
    if (getline(in_file,str)) {
        while (num < str.size()) {
            ch = str[num];
            if (ch == ' '){
                num++;
                kind.clear();
            }
            if (isalpha(ch)) {//IDN
                while (true) {
                    num++;
                    if (num != str.size()) {
                        ch = str[num];
                        if (isalpha(ch) || isalnum(ch)|| ch == '_') {
                            continue;
                        }
                    }
                    break;
                }
                kind = IDN;
            }
            else if (isalnum(ch) && ch != '0') {//INT10 or DOUBLE
                int INTorDOUBLE = 0;
                while (true)
                {
                    num++;
                    if (num != str.size()) {
                        ch = str[num];

                        if (isalnum(ch)) {
                            continue;
                        }
                        if (INTorDOUBLE == 0&&ch == '.'){
                            INTorDOUBLE = 1;
                            continue;
                        }
                    }
                    break;
                }
                if(INTorDOUBLE){
                    kind = REAL10;
                }
                else
                    kind = INT10;
            }
            else if (ch == '0') {//INT
                num++;
                if (num != str.size()) {
                    ch = str[num];
                    if (ch == 'o' || ch == 'O') {
                        int INTorDOUBLE = 0;
                        while (true)
                        {
                            num++;
                            if (num != str.size()) {
                                ch = str[num];
                                if (is8(ch)) {
                                    continue;
                                }
                                if (INTorDOUBLE == 0 && ch == '.') {
                                    INTorDOUBLE = 1;
                                    continue;
                                }
                            }
                            break;
                        }
                        if(INTorDOUBLE == 1){
                            kind = REAL8;
                        }
                        else
                            kind = INT8;
                    }
                    else if (ch == 'x' || ch == 'X') {
                        int INTorDOUBLE = 0;
                        while (true)
                        {
                            num++;
                            if (num != str.size()) {
                                ch = str[num];
                                if (is16(ch)) {
                                    continue;
                                }
                                if (INTorDOUBLE == 0 && ch == '.') {
                                    INTorDOUBLE = 1;
                                    continue;
                                }
                            }
                            break;
                        }
                        if(INTorDOUBLE == 1){
                            kind = REAL16;
                        }
                        else
                            kind = INT16;
                    }
                    else if(ch == '.') {
                        while (true){
                            num++;
                            if (num != str.size()){
                                ch = str[num];
                                if (isalnum(ch)){
                                    continue;
                                }
                            }
                            break;
                        }
                        kind = REAL10;

                    }
                }
                else {
                    kind = INT10;
                }
            }
            else if (isOperator(ch)) {
                num++;
                kind = OP;
            }

            string token = str.substr(0, num);
            if (kind == IDN && isKeyWord(token)) {
                kind = KEY;
            }

            out_file << fixed;
            out_file.precision(2);
            out_file.setf(ios_base::showpoint);
            if (kind == OP){
                cout << token << "\t" << '_' << endl;
                out_file << token << "\t" << '_' << endl;
            }
            else if(kind == INT8 || kind == REAL8){
                cout << kind << "\t" << Oct2Dec(token) << endl;
                out_file << kind << "\t" << Oct2Dec(token) << endl;
            }
            else if(kind == INT16 || kind == REAL16) {
                cout << kind << "\t" << Hex2Dec(token) << endl;
                out_file << kind << "\t" << Hex2Dec(token) << endl;
            }
            else if(!kind.empty()){
                cout << kind << "\t" << token << endl;
                out_file << kind << "\t" << token << endl;
            }

            if (num != str.size()) {
                str = str.substr(num);
                num = 0;
                ch = str[num];
                continue;
            }
            break;
        }
        return 1;
    }
    return 0;
}



int main() {
    ifstream in_file;
    ofstream out_file;
    in_file.open("G:\\Desktop\\compile\\compile\\exp1\\test.txt");
    out_file.open("out.txt");
    while (scan(in_file,out_file));
    in_file.close();
    out_file.close();
    return 0;
}
